﻿#define  _CRT_SECURE_NO_WARNINGS


#include<iostream>
#include<list>
#include<vector>
#include<string>
#include<algorithm>
#include<thread>
#include<assert.h>
using namespace std;


// recursive_mutex递归互斥锁，lock_guard，unique_lock，atomic支持CAS，condition_variabl:ewait和notify系列，function包装器:包装静/动态成员，OJ逆波兰表达式求值


#include<mutex>// 加锁
//
//int x = 0;
//mutex mtx;
//
//void Func(int n)
//{
//	//cout << &n << endl;
//	//cout << &x << endl;
//	// 并行  ---  加锁解锁消耗，切换上下文的消耗
//	for (int i = 0; i < n; i++)
//	{
//		mtx.lock();
//		++x;
//		mtx.unlock();
//	}
//
//	// 快
//	// 串行
//	//mtx.lock();
//	//for (int i = 0; i < n; i++)
//	//{
//	//	++x;
//	//}
//	//mtx.unlock();
//}
//
//int main()
//{
//	int n = 10000000;
//	size_t begin = clock();
//
//	thread t1(Func, n);
//	thread t2(Func, n);
//
//	t1.join();
//	t2.join();
//	size_t end = clock();
//
//	cout << x << endl;
//	cout << end - begin << endl;
//
//	return 0;
//}
// 
// 


//list<int> lt;
//int x = 0;
//mutex mtx;
//
//void Func(int n)
//{
//	//cout << &n << endl;
//	//cout << &x << endl;
//	// 并行  ---  当外围消耗在增重，并行效率会增加
//	for (int i = 0; i < n; i++)
//	{
//		mtx.lock();
//		++x;
//		lt.push_back(x);
//		lt.push_back(x);
//		mtx.unlock();
//
//		cout << i << endl;
//		cout << i << endl;
//		cout << i << endl;
//	}
//
//	// 快
//	// 串行
//	/*mtx.lock();
//	for (int i = 0; i < n; i++)
//	{
//		++x;
//		lt.push_back(x);
//		lt.push_back(x);
//
//		cout << i << endl;
//		cout << i << endl;
//		cout << i << endl;
//	}
//	mtx.unlock();*/
//}
//
//int main()
//{
//	int n = 1000;
//	size_t begin = clock();
//
//	thread t1(Func, n);
//	thread t2(Func, n);
//
//	t1.join();
//	t2.join();
//	size_t end = clock();
//
//	cout << x << endl;
//	cout << end - begin << endl;
//
//	return 0;
//}


// C++11使用lambda简化写法
// 
//int main()
//{
//	int n = 100000;
//	int x = 0;
//	mutex mtx;
//	size_t begin = clock();
//
//	thread t1([&, n](){
//			mtx.lock();
//			for (int i = 0; i < n; i++)
//			{
//				++x;
//			}
//			mtx.unlock();
//		});
//
//	thread t2([&, n]() {
//			mtx.lock();
//			for (int i = 0; i < n; i++)
//			{
//				++x;
//			}
//			mtx.unlock();
//		});
//
//	t1.join();
//	t2.join();
//	size_t end = clock();
//
//	cout << x << endl;
//	cout << end - begin << endl;
//
//	return 0;
//}
// 
// 
// 
//int x = 0;
//recursive_mutex mtx;// 递归互斥锁，防止递归过程中自己锁住自己导致自己无法执行
//
//void Func(int n)
//{
//	if (n == 0)
//		return;
//
//	mtx.lock();
//	++x;
//
//	Func(n - 1);
//
//	mtx.unlock();
//}
//
//int main()
//{
//	thread t1(Func, 10000);
//	thread t2(Func, 20000);
//
//	t1.join();
//	t2.join();
//
//	cout << x << endl;
//
//	return 0;
//}
// 
// 
//template<class Lock>
//class LockGuard
//{
//public:
//	LockGuard(Lock& lk)
//		:_lk(lk)
//	{
//		_lk.lock();
//	}
//
//	~LockGuard()
//	{
//		_lk.unlock();
//	}
//
//private:
//	Lock& _lk;// 成员变量为引用
//};
//
//int x = 0;
//mutex mtx;
//
//void Func(int n)
//{
//	for (int i = 0; i < n; i++)
//	{
//		try
//		{
//			//mtx.lock();
//			//LockGuard<mutex> lock(mtx);// 借助类的构造函数和析构函数解决加锁了但出错没有解锁的情况
//			//lock_guard<mutex> lock(mtx);// lock_guard，为库模板，可以创建一个防止未解锁情况的对象
//			unique_lock<mutex> lock(mtx);// unique_lock，为模板库，可以在lock_guard的基础上在中间加锁和解锁操作
//			++x;
//
//			//lock.unlock();
//			////...
//			//lock.lock();
//
//
//			// .... 抛异常
//			if (rand() % 3 == 0)
//			{
//				throw exception("抛异常");
//			}
//			//mtx.unlock();
//		}
//		catch (const exception& e)
//		{
//			cout << e.what() << endl;
//		}
//	}
//	
//}
//int main()
//{
//	
//	thread t1(Func, 10);
//	thread t2(Func, 10);
//
//	t1.join();
//	t2.join();
//
//	cout << x << endl;
//
//	return 0;
//}
// 
// 
// atomic，支持CAS的一系列操作
// 
// + - && || ++ --
// 
//void Func(int x)
//{
//	cout << x << endl;
//}
//
//int main()
//{
//	int n = 100000;
//	atomic<int> x = 0;
//	//atomic<int> x = {0};
//	//atomic<int> x{0};
//	//int x = 0;
//
//	mutex mtx;
//	size_t begin = clock();
//
//	thread t1([&, n](){
//			for (int i = 0; i < n; i++)
//			{
//				++x;
//			}
//		});
//
//	thread t2([&, n]() {
//			for (int i = 0; i < n; i++)
//			{
//				++x;
//			}
//		});
//
//	t1.join();
//	t2.join();
//	size_t end = clock();
//
//	cout << x << endl;
//	cout << end - begin << endl;
//	
//	//Func(x);
//	//printf("%d\n", x.load());
//
//	return 0;
//}
// 
// 
// 
// 
// 
// condition_variable
// 类封装的 条件变量，wait 和 notify系列   ----   经典案例
// 
//#include<condition_variable>
//
// // 支持两个线程交替打印，t1打印奇数，t2打印偶数
//int main()
//{
//	mutex mtx;// 创建一个公共锁
//	condition_variable cv;// 创建一个公共环境变量
//
//	int n = 100;
//	int x = 1;
//
//	// 问题1：如何保证t1先运行，t2阻塞？
//	// 问题2：如何防止一个线程不断运行？
//	// 分析:
//	// 1 : t1先抢到锁, t2后抢到锁t1先运行，t2阻塞在锁上面
//	// 2 : t2先抢到锁, t1后抢到锁t2先运行，t1阻塞在锁上面。但是t2会被下一步wait阻塞。并且wait时会解锁，保证了t1先运行
//
//	thread t1([&, n]() {
//		while (1)
//		{
//			unique_lock<mutex> lock(mtx);// 出作用域自动解锁，并且中途可以解锁加锁
//			if (x >= 100)
//				break;
//
//			//if (x % 2 == 0) // 偶数就阻塞 --- 防止连续运行
//			//{
//			//	cv.wait(lock);
//			//}
//			cv.wait(lock, [&x]() {return x % 2 != 0; });
//			// false 阻塞
//			// true 不阻塞
//
//			cout << this_thread::get_id() << ":" << x << endl;
//			++x;
//
//			cv.notify_one();
//		}
//		});
//
//	thread t2([&, n]() {
//		while (1)
//		{
//			unique_lock<mutex> lock(mtx);
//			if (x > 100)
//				break;
//
//			//if (x % 2 != 0) // 奇数就阻塞  ---  防止连续运行
//			//{
//			//	cv.wait(lock);
//			//}
//			cv.wait(lock, [&x](){return x % 2 == 0; });
//
//
//			cout << this_thread::get_id() << ":" << x << endl;
//			++x;
//
//			cv.notify_one();
//		}
//		});
//
//	t1.join();
//	t2.join();
//
//	return 0;
//}
// 





// 11.包装器
// 
// function包装器
// function包装器 也叫作适配器。C++中的function本质是一个类模板，也是一个包装器。
// 
// 包装器 -- 可调用对象类型进行再封装适配
// 函数指针
// 仿函数
// lambda
// 
// std::function在头文件<functional>
//// 类模板原型如下
// template <class T> function;   // undefined
// template <class Ret, class... Args>
// class function<Ret(Args...)>;
// 模板参数说明：
// Ret : 被调用函数的返回类型
// Args…：被调用函数的形参
// 
// 
#include<map>
#include<functional>

int f(int a, int b)
{
	cout << "int f(int a, int b)" << endl;
	return a + b;
}

struct Functor
{
public:
	int operator() (int a, int b)
	{
		cout << "int operator() (int a, int b)" << endl;

		return a + b;
	}
};



//int main()
//{
//	//int(*pf1)(int,int) = f;// 函数指针
//	//map<string, >
//
//	function<int(int, int)> f1 = f;// 包装 一个函数为一个 适配器（包装器）对象
//	function<int(int, int)> f2 = Functor();// 包装 一个访函数为一个 适配器（包装器）对象
//	function<int(int, int)> f3 = [](int a, int b) {
//		cout << "[](int a, int b) {return a + b;}" << endl;
//		return a + b;
//	};// 包装 一个lambda为一个 适配器（包装器）对象
//
//	cout << f1(1, 2) << endl;
//	cout << f2(10, 20) << endl;
//	cout << f3(100, 200) << endl;
//
//	map<string, function<int(int, int)>> opFuncMap;
//	opFuncMap["函数指针"] = f;
//	opFuncMap["仿函数"] = Functor();
//	opFuncMap["lambda"] = [](int a, int b) {
//		cout << "[](int a, int b) {return a + b;}" << endl;
//		return a + b;
//	};
//	cout << opFuncMap["lambda"](1, 2) << endl;
//
//	return 0;
//}
// 
// 
// 
// 
// 包装器的其他一些场景：逆波兰表达式求值
// 
// https://leetcode-cn.com/problems/evaluate-reverse-polish-notation/submissions/
// 
//class Solution {
//public:
//    int evalRPN(vector<string>& tokens) {
//        stack<int> st;// 创建一个栈对象
//
//        map<string, function<int(int, int)>> opFuncMap =
//        {
//            {"+",[](int a, int b) {return a + b; }},
//            {"-",[](int a, int b) {return a - b; }},
//            {"*",[](int a, int b) {return a * b; }},
//            {"/",[](int a, int b) {return a / b; }},
//        };
//
//        for (auto& str : tokens)
//        {
//            // 判断是否为运算符
//            if (opFuncMap.count(str))
//            {
//                // 若为运算符则从栈顶取出右操作数 和 左操作数
//                int right = st.top();
//                st.pop();
//                int left = st.top();
//                st.pop();
//
//                //插入结果
//                st.push(opFuncMap[str](left, right));
//            }
//            else
//            {
//                // 若是操作数则压入栈中
//                st.push(stoi(str));
//            }
//        }
//        return st.top();
//    }
//};
// 
// 
// 
// 
// 
// 包装静态成员，
class Plus
{
public:
	Plus(int rate = 2)
		:_rate(rate)
	{}

	static int plusi(int a, int b)// 静态成员函数
	{
		return a + b;
	}

	double plusd(double a, double b)
	{
		return (a + b) * _rate;
	}

private:
	int _rate = 2;
};

int main()
{
	// 静态成员函数，指定类域直接封装（静态成员函数也可以加上&）
	function<int(int, int)> f1 = &Plus::plusi;
	//function<int(int, int)> f1 = Plus::plusi;
	// 非静态成员函数，需要指定类域，标明该类的类型（不能是指针，为指针必须传入左值），并增加&，取地址符
	function<double(Plus, double, double)> f2 = &Plus::plusd;

	cout << f1(1, 2) << endl;
	cout << f2(Plus(), 20, 20) << endl;// 调用时需要给出该类的对象

	Plus pl(3);
	cout << f2(pl, 20, 20) << endl;

	return 0;
}

// 
// 